//----------------------------------Include-------------------------------------
#include "mcu.h"
//------------------------------------------------------------------------------

//-----------------------------------Macro--------------------------------------
#define _UART_UNIT               (HPM_UART0)
#define _INT_IRQn                (UART0_INT_IRQn)
//------------------------------------------------------------------------------
#define _DMA_TX                  1
#define _DMA_CHN_TX              0
//------------------------------------------------------------------------------
#define _DMA_RX                  0
#define _DMA_CHN_RX              1
//------------------------------------------------------------------------------
#define _RXBUF_LEN               (64)
//------------------------------------------------------------------------------

//--------------------------------Static Var------------------------------------
static uint32_t                   src_clk;
//------------------------------------------------------------------------------
#if _DMA_TX == 1
static dma_handshake_config_t     nt_dma_tx_cfg;
#endif
#if _DMA_RX == 1
static dma_handshake_config_t     nt_dma_rx_cfg;
static uint32_t                   nu32_cnt;
static uint32_t                   nu32_done;
static ATTR_PLACE_AT_NONCACHEABLE uint8_t    nrxbuf[_RXBUF_LEN];
#endif
//------------------------------------------------------------------------------

//--------------------------------Static Func-----------------------------------
#if _DMA_RX == 1
//for DMA receive
static uint32_t _get_rcv_addr(void)
{
  return (uint32_t)&nrxbuf[0];
//return core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)nrxbuf);
}

static uint32_t _get_rcv_size(void)
{
  return _RXBUF_LEN;
}

static void _it_dma_rcv_done(uint32_t cnt)
{
  nu32_cnt   = cnt;
  nu32_done  = 1;
}
#endif
//------------------------------------------------------------------------------

//------------------------------------ISR---------------------------------------
SDK_DECLARE_EXT_ISR_M(IRQn_UART0, _isr_uart0);
void _isr_uart0(void)
{
#if _DMA_RX == 1
  if(uart_is_rxline_idle(_UART_UNIT)){
    uart_clear_rxline_idle_flag(_UART_UNIT);
    dma_disable_channel(HPM_HDMA, _DMA_CHN_RX);
    //uart_reset_rx_fifo(_UART_UNIT);
    //uart_clear_rx_fifo(_UART_UNIT);

    uint32_t  n, buflen;
    n      = dma_get_remaining_transfer_size(HPM_HDMA, _DMA_CHN_RX);
    buflen = _get_rcv_size();
    if(buflen > n) _it_dma_rcv_done(buflen - n);
    //start next receive
    nt_dma_rx_cfg.dst          = _get_rcv_addr();
    nt_dma_rx_cfg.size_in_byte = _get_rcv_size();
    dma_setup_handshake(HPM_HDMA, &nt_dma_rx_cfg, true);
  }
#else
  static  uint8_t  irq_id;
  static  uint8_t  d;

  irq_id = uart_get_irq_id(_UART_UNIT);
  if(irq_id == uart_intr_id_rx_data_avail){
    d = _UART_UNIT->RBR;
    d = d;
  }
#endif
}
//------------------------------------------------------------------------------

//--------------------------------Public Func-----------------------------------
void mcu_init_uart0(void)
{
//periph clock
  clock_add_to_group(clock_uart0, 0);
  
//pin
  //PY06--U0TX    PY07 -- U0RX
  HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD;
  HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD;
  /* PY port IO needs to configure PIOC */
  HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07;
  HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06;
  
//uart
  clock_set_source_divider(clock_uart0, clk_src_osc24m, 1);  /* Configure the UART clock to 24MHz */
  src_clk = clock_get_frequency(clock_uart0);
  
  uart_config_t   cfg;
  uart_default_config(_UART_UNIT, &cfg);
  cfg.src_freq_in_hz   = src_clk;
  cfg.baudrate         = 115200;
  cfg.num_of_stop_bits = stop_bits_1;
  cfg.word_length      = word_length_8_bits;
  cfg.parity           = parity_none;
  cfg.tx_fifo_level    = uart_tx_fifo_trg_not_full;
  cfg.rx_fifo_level    = uart_rx_fifo_trg_not_empty;

#if _DMA_RX == 1 || _DMA_TX == 1
  cfg.dma_enable       = true;
  cfg.fifo_enable      = true;
#else
  cfg.dma_enable       = false;
  cfg.fifo_enable      = true;
#endif

  //6300 系列没有接收空闲检测
#if _DMA_RX == 1
#else
#endif
  uart_init(_UART_UNIT, &cfg);

#if _DMA_TX == 1
  dmamux_config(HPM_DMAMUX, DMA_SOC_CHN_TO_DMAMUX_CHN(HPM_HDMA, _DMA_CHN_TX), HPM_DMA_SRC_UART0_TX, true);

  dma_default_handshake_config(HPM_HDMA, &nt_dma_tx_cfg);
  nt_dma_tx_cfg.ch_index     = _DMA_CHN_TX;
  nt_dma_tx_cfg.dst          = (uint32_t)&_UART_UNIT->THR;
  nt_dma_tx_cfg.dst_fixed    = true;
//nt_dma_tx_cfg.src          = src;
  nt_dma_tx_cfg.src_fixed    = false;
  nt_dma_tx_cfg.data_width   = DMA_TRANSFER_WIDTH_BYTE;
//nt_dma_tx_cfg.size_in_byte = size;
#endif

#if _DMA_RX == 1
  dmamux_config(HPM_DMAMUX, DMA_SOC_CHN_TO_DMAMUX_CHN(HPM_HDMA, _DMA_CHN_RX), HPM_DMA_SRC_UART0_RX, true);

  dma_default_handshake_config(HPM_HDMA, &nt_dma_rx_cfg);
  nt_dma_rx_cfg.ch_index     = _DMA_CHN_RX;
  nt_dma_rx_cfg.dst          = (uint32_t)&nrxbuf[0];
  nt_dma_rx_cfg.dst_fixed    = false;
  nt_dma_rx_cfg.src          = (uint32_t)&_UART_UNIT->RBR;
  nt_dma_rx_cfg.src_fixed    = true;
  nt_dma_rx_cfg.data_width   = DMA_TRANSFER_WIDTH_BYTE;
  nt_dma_rx_cfg.size_in_byte = _RXBUF_LEN;
  dma_setup_handshake(HPM_HDMA, &nt_dma_rx_cfg, true);

  //interrupt
  //uart_enable_irq(_UART_UNIT, uart_intr_rx_line_idle);  //如果 rxidle_config.detect_irq_enable = true 时，会在 uart_init 中使能空闲中断
  intc_m_enable_irq_with_priority(IRQn_UART0, 12);
#else
  //interrupt
  uart_enable_irq(_UART_UNIT, uart_intr_rx_data_avail_or_timeout);
  intc_m_enable_irq_with_priority(IRQn_UART0, 12);
#endif

//enable
}

void mcu_uart0_tx(char* p,  uint32_t sz)
{
  uint32_t  i;
  for(i=0; i<sz; i++){
    uart_send_byte(_UART_UNIT, p[i]);
  }
  uart_flush(_UART_UNIT);
}

void mcu_uart0_dma_tx(char* p,  uint32_t sz)
{
#if _DMA_TX == 1
  if(sz > 0){
    nt_dma_tx_cfg.src          = (uint32_t)p;
    nt_dma_tx_cfg.size_in_byte = sz;
    dma_setup_handshake(HPM_HDMA, &nt_dma_tx_cfg, true);
  }
#endif
}
//------------------------------------EOF---------------------------------------




